雖然不一定要掌握 Dart 才可以開始 Flutter 的開發工作,不過至少要理解基礎的語法結構以及語言的特性。
Dart程式語言是一款由 goolge 主導開發,於2011年10月公開,當初的目標是發展成為下一代的 Web 開發語言,不過 Javascript 當時已被各瀏覽器所支持又遇到 nodejs 使用前端應用框架的興起,初期並沒有獲得較多開發人員的青睞,不過在這段時間裡 dart 慢慢從當初瀏覽器的範疇跨足到移動開發的領域,並且吸收許多不同程式語言的優點,轉變成一個效能高且更加安全的強型別程式語言,因此在學習dart的過程中,我們發現許多目前主流程式語言相類似語法(Java、TypeScrip…)。
對於有一定經驗的 "程式猿" 來說,學習Dart應該不是太大的難度。可拜讀官網上的技術文件。
Dart 中每個變數參照的都是 Object,每個 Object 都是一個 Class 的 instance,除了 null 之外,所有的 Class 都是繼承自 Object。
與 JavaScript 這種弱型別相比,Dart 是強型別的的程式語言。
對於 JavaScript 是動態類型的語言,而 Dart 則是靜態類型語言。
所謂的動態類型指的是在運行期間才去檢查型別檢查的語系,而靜態語言則是在編譯階段進行檢查。
null-safety
原則,也就是說變數在宣告時預設不得為空(null),除非你明確聲明此變數可為空。int? aNullableInt;
Dart 支持泛型,這是一種在強型別語系上常見的編碼風格。
與 Java 相比較,Dart 沒有類似 public
、protected
、private
存取權限的修飾符,在變數名稱命名上若以下底線(_)開頭的即表現該變數為私有,是不是很像 JS 的風格。
類似Java應用程式,運行程式的入口為 main() 函数
void main() {
print("hello world");
}
在 termianl 可以使用 dart
指令可以執行程式內容
❯ dart hello.dart
hello world
dart 可以透過值推論出該值的型別為何,因此可以使用 var
+ 變數名稱 完成變數的宣告,下面是在開發時常見的基礎型別:
//String
var aString = "I am a String";
print(aString.runtimeType); // String
// Numbers
var aInterger = 1;
print(aInterger.runtimeType); // int
var aDobule = 0.1;
print(aDobule.runtimeType); // dobule
// Booleans
var aTrue = true;
print(aTrue.runtimeType); // bool
// Lists or Array
var aList = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
print(aList.runtimeType); // List<int>
// Maps
var aMap = {"type": "Mobile Development", "title": "flutter"};
print(aMap.runtimeType); // _InternalLinkedHashMap<String, String>
// Sets
var aSet = {"a", "b", "c", "d", "e"};
print(aSet.runtimeType); // _CompactLinkedHashSet<String>
// Null
var aNull = null;
print(aNull.runtimeType); // Null
// Runes
var emoji = "?";
print(emoji.runes.runtimeType); // Runes
// Symbols
var aSymbol = Symbol("ithome");
print(aSymbol); // Symbol("ithome")
另外也可以在變數名稱前明確宣告變數的型別
int num = 1;
每款程式語言都有其特色的語法,google工程師們已幫我們整理出 dart-cheatsheet,內容如下:
類似 es6 的字串樣版語法,有變數
或表達式
兩種寫法可以使用
// 變數
var activity = "鐵人賽";
print("我參加了$activity"); // 我參加了鐵人賽
// 表達式:內含運算子的一段程式
// + - * / ~/ %
var num = 29;
print("這需要連續挑戰${num + 1}天"); // 這需要連續挑戰30天
Dart為了更完善的健全null-safe
,變數預設上不可為空
int aIntOfNull = null;
系統將會提示以下訊息
A value of type 'Null' can't be assigned to a variable of type 'int'.
Try changing the type of the variable, or casting the right-hand type to 'int'.dart(invalid_assignment)
若需要使用 null 時,需要使用(?)明確的宣告
int? aIntOfNull;
可以使用??
檢查左側的代碼是否為空
int? aNumOfnulll;
aNumOfnulll ??= 1;
print(aNumOfnulll); // 1
Dart 提供三種類型的集合字面值設定,分別為 List、Set、Map
var aList = ["a", "b", "c", "d"];
print(aList); // [a, b, c, d]
var aSet = {"a", "b", "c", "d"};
print(aSet); // {a, b, c, d}
var aMap = {"a": "a", "b": "b", "c": "c", "d": "d"};
print(aMap); // {a: a, b: b, c: c, d: d}
有點類似 JS 的箭頭語法,主要用來進行單行函式簡寫使用。
import 'dart:math' as math;
void main() {
var aListOfNum = [1, 2, 3, 4];
var aListOfNumByPow = aListOfNum.map((num) => math.pow(num, 2)).toList();
print(aListOfNumByPow); // [1, 4, 9, 16]
}
雖然 Cascades 在 dart.cn 上翻譯為"級連",不過我從國家教育研究院上的詞彙查詢得到學術名詞感覺"串級"會比較貼切一些。
這個在 JS 上為了在實體化物件後可以達到函式鏈結的行為,我們大都會在函式中將this
當作回傳值傳出,以方便鏈式的呼叫該實例的方法。我分別使用 JS 以及 Dart 寫了一個日期時間的類別,比較串級在不同程式語言上的實作方式。
/// NOTE:這邊是js的語法
class DateTime {
_date = null;
constructor() {
this._date = new Date();
}
add(num, type) {
switch (type) {
case 'days':
this._addDays(num);
break;
default:
}
return this;
}
setDate(newDate) {
this._date = newDate;
}
_addDays(num) {
this._date.setDate(this._date.getDate() + num);
return this;
}
toString() {
return this._date.toString();
}
}
const date = new DateTime();
// 函式鏈結
const result =
date
.setDate(new Date(2021, 8, 2, 0, 0, 0))
.add(30, 'days')
.toString();
console.log(result); // Sat Oct 02 2021 00:00:00 GMT+0800 (台北標準時間)
Dart 中如果要對同一對象執行函式鏈結的操作,只需要使用串級的語法即可,比較上下兩段程式碼可以發現 Dart 在程式上的行數明顯少了許多。
class MyDateTime {
DateTime _date;
MyDateTime() : _date = DateTime.now();
add(int num, String type) {
switch (type) {
case 'days':
_addDays(num);
break;
default:
}
}
setDate(DateTime date) {
_date = date;
return _date; // 使用(.)與(..)取得的內容會不一樣
}
_addDays(int num) {
_date = _date.add(Duration(days: num));
}
toString() {
return _date.toString();
}
}
void main() {
var date = MyDateTime();
var result = date
..setDate(DateTime(2021, 8, 2))
..add(30, 'days')
..toString();
print(result); // 2021-09-01 00:00:00.000
var dateTime = MyDateTime().setDate(DateTime(2021, 8, 2));
print(dateTime.runtimeType); // DateTime
var myDateTime = MyDateTime()..setDate(DateTime(2021, 8, 2));
print(myDateTime.runtimeType); // MyDateTime
}
官方速查表中可以練習的題目,請試著解答這些問題。